package com.skyjing.askit

import android.content.Context
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.graphics.drawable.NinePatchDrawable
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat

object AsToast {
    @ColorInt
    private val DEFAULT_TEXT_COLOR = Color.parseColor("#FFFFFF")
    @ColorInt
    private val ERROR_COLOR = Color.parseColor("#FD4C5B")
    @ColorInt
    private val INFO_COLOR = Color.parseColor("#2196F3")
    @ColorInt
    private val SUCCESS_COLOR = Color.parseColor("#52BA97")
    @ColorInt
    private val WARNING_COLOR = Color.parseColor("#FFA900")
    private const val TOAST_TYPEFACE = "sans-serif-condensed"
    private var currentToast: Toast? = null

    /***********************************************************************************************
     * normal
     */
    @JvmStatic
    fun normal(message: String){
        normal(
            message,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun normal(messageResId: Int){
        normal(
            "${AsTool.getContent()?.getText(messageResId)}",
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun normal(message: String , duration: Int){
        normal(
            message,
            duration,
            DEFAULT_TEXT_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun normal(messageResId: Int , duration: Int){
        normal(
            "${AsTool.getContent()?.getText(messageResId)}",
            duration,
            DEFAULT_TEXT_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun normal(message: String , duration: Int , gravity: Int){
        normal(
            message,
            duration,
            DEFAULT_TEXT_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun normal(messageResId: Int , duration: Int , gravity: Int){
        normal(
            "${AsTool.getContent()?.getText(messageResId)}",
            duration,
            DEFAULT_TEXT_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun normal(message: String, @ColorInt textColor: Int = DEFAULT_TEXT_COLOR,
               @ColorInt tintColor: Int = -1, duration: Int){
        baseCustom(
            message, null, textColor, tintColor, 0, 0, 0,
            duration, withIcon = false, shouldTint = false
        )?.show()
    }

    @JvmStatic
    fun normal(message: String, duration: Int = Toast.LENGTH_SHORT,
               @ColorInt textColor: Int = DEFAULT_TEXT_COLOR, gravity: Int = 0,
               xOffset: Int  = 0, yOffset: Int = 0) {
        baseCustom(
            message, null, textColor, -1, gravity, xOffset, yOffset,
            duration, withIcon = false, shouldTint = false
        )?.show()
    }


    /***********************************************************************************************
     * info
     */
    @JvmStatic
    fun info(message: String){
        info(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_info
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun info(messageResId: Int){
        info(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_info
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun info(message: String , duration: Int){
        info(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_info
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun info(messageResId: Int , duration: Int){
        info(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_info
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun info(message: String , duration: Int , gravity: Int){
        info(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_info
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun info(messageResId: Int , duration: Int , gravity: Int){
        info(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_info
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun info(message: String , icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_info
    )
    ){
        info(
            message,
            icon,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun info(messageResId: Int , icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_info
    )
    ){
        info(
            "${AsTool.getContent()?.getText(messageResId)}",
            icon,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            INFO_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun info(message: String, @ColorInt textColor: Int = DEFAULT_TEXT_COLOR,
             @ColorInt tintColor: Int = -1, duration: Int){
        baseCustom(
            message, getDrawable(
                AsTool.getContent(),
                R.drawable.toast_info
            ), textColor, tintColor, 0, 0, 0,
            duration, withIcon = false, shouldTint = false
        )?.show()
    }

    @JvmStatic
    fun info(message: String, icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_info
    ), duration: Int = Toast.LENGTH_SHORT,
             @ColorInt textColor: Int = DEFAULT_TEXT_COLOR, @ColorInt tintColor: Int = INFO_COLOR,
             gravity: Int = 0, xOffset: Int  = 0, yOffset: Int = 0){
        baseCustom(
            message, icon, textColor, tintColor, gravity, xOffset, yOffset,
            duration, withIcon = true, shouldTint = true
        )?.show()
    }

    /***********************************************************************************************
     *warning
     */
    @JvmStatic
    fun warning(message: String){
        warning(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_warning
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(messageResId: Int){
        warning(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_warning
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(message: String , duration: Int){
        warning(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_warning
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(messageResId: Int , duration: Int){
        warning(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_warning
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(message: String , duration: Int , gravity: Int){
        warning(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_warning
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(messageResId: Int , duration: Int , gravity: Int){
        warning(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_warning
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(message: String , icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_warning
    )
    ){
        warning(
            message,
            icon,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(messageResId: Int , icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_warning
    )
    ){
        warning(
            "${AsTool.getContent()?.getText(messageResId)}",
            icon,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            WARNING_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun warning(message: String, @ColorInt textColor: Int = DEFAULT_TEXT_COLOR,
                @ColorInt tintColor: Int = -1, duration: Int){
        baseCustom(
            message, getDrawable(
                AsTool.getContent(),
                R.drawable.toast_warning
            ), textColor, tintColor, 0, 0, 0,
            duration, withIcon = false, shouldTint = false
        )?.show()
    }

    @JvmStatic
    fun warning(message: String, icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_warning
    ), duration: Int = Toast.LENGTH_SHORT,
                @ColorInt textColor: Int = DEFAULT_TEXT_COLOR, @ColorInt tintColor: Int = WARNING_COLOR,
                gravity: Int = 0, xOffset: Int  = 0, yOffset: Int = 0){
        baseCustom(
            message, icon, textColor, tintColor, gravity, xOffset, yOffset,
            duration, withIcon = true, shouldTint = true
        )?.show()
    }

    /***********************************************************************************************
     *error
     */
    @JvmStatic
    fun error(message: String){
        error(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_error
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            ERROR_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun error(messageResId: Int){
        error(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_error
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            ERROR_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun error(message: String , duration: Int){
        error(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_error
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            ERROR_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun error(messageResId: Int , duration: Int){
        error(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_error
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            ERROR_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun error(message: String , duration: Int , gravity: Int){
        error(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_error
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            ERROR_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun error(messageResId: Int , duration: Int , gravity: Int){
        error(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_error
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            ERROR_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun error(message: String , icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_error
    )
    ){
        error(
            message,
            icon,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            ERROR_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun error(message: String, @ColorInt textColor: Int = DEFAULT_TEXT_COLOR,
              @ColorInt tintColor: Int = -1, duration: Int){
        baseCustom(
            message, getDrawable(
                AsTool.getContent(),
                R.drawable.toast_error
            ), textColor, tintColor, 0, 0, 0,
            duration, withIcon = false, shouldTint = false
        )?.show()
    }

    @JvmStatic
    fun error(message: String, icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_error
    ), duration: Int = Toast.LENGTH_SHORT,
              @ColorInt textColor: Int = DEFAULT_TEXT_COLOR, @ColorInt tintColor: Int = ERROR_COLOR,
              gravity: Int = 0, xOffset: Int  = 0, yOffset: Int = 0){
        baseCustom(
            message, icon, textColor, tintColor, gravity, xOffset, yOffset,
            duration, withIcon = true, shouldTint = true
        )?.show()
    }

    /***********************************************************************************************
     *success
     */
    @JvmStatic
    fun success(message: String){
        success(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_success
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            0,
            0,
            0
        )
    }
    @JvmStatic
    fun success(messageResId: Int){
        success(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_success
            ),
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun success(message: String , duration: Int){
        success(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_success
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun success(messageResId: Int , duration: Int){
        success(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_success
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun success(message: String , duration: Int , gravity: Int){
        success(
            message,
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_success
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun success(messageResId: Int , duration: Int , gravity: Int){
        success(
            "${AsTool.getContent()?.getText(messageResId)}",
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_success
            ),
            duration,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            gravity,
            0,
            0
        )
    }

    @JvmStatic
    fun success(message: String , icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_success
    )
    ){
        success(
            message,
            icon,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun success(messageResId: Int , icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_success
    )
    ){
        success(
            "${AsTool.getContent()?.getText(messageResId)}",
            icon,
            Toast.LENGTH_SHORT,
            DEFAULT_TEXT_COLOR,
            SUCCESS_COLOR,
            0,
            0,
            0
        )
    }

    @JvmStatic
    fun success(message: String, @ColorInt textColor: Int = DEFAULT_TEXT_COLOR,
                @ColorInt tintColor: Int = -1, duration: Int){
        baseCustom(
            message, getDrawable(
                AsTool.getContent(),
                R.drawable.toast_success
            ), textColor, tintColor, 0, 0, 0,
            duration, withIcon = false, shouldTint = false
        )?.show()
    }

    @JvmStatic
    fun success(message: String, icon: Drawable? = getDrawable(
        AsTool.getContent(),
        R.drawable.toast_success
    ), duration: Int = Toast.LENGTH_SHORT,
                @ColorInt textColor: Int = DEFAULT_TEXT_COLOR, @ColorInt tintColor: Int = SUCCESS_COLOR,
                gravity: Int = 0, xOffset: Int  = 0, yOffset: Int = 0){
        baseCustom(
            message, icon, textColor, tintColor, gravity, xOffset, yOffset,
            duration, withIcon = true, shouldTint = true
        )?.show()
    }

    /***********************************************************************************************
     * baseCustom
     */
    private fun baseCustom(
        message: String, icon: Drawable?, @ColorInt textColor: Int,
        @ColorInt tintColor: Int, gravity: Int, xOffset: Int, yOffset: Int,
        duration: Int, withIcon: Boolean, shouldTint: Boolean): Toast? {
        if (currentToast == null) {
            currentToast = Toast(AsTool.getContent())
        } else {
            currentToast?.cancel()
            currentToast = null
            currentToast = Toast(AsTool.getContent())
        }
        val toastLayout =
            (AsTool.getContent()?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as
                    LayoutInflater).inflate(R.layout.toast_layout, null)
        val toastIcon = toastLayout.findViewById<ImageView>(R.id.toast_icon)
        val toastTextView = toastLayout.findViewById<TextView>(R.id.toast_text)
        val drawableFrame = if (shouldTint) {
            tint9PatchDrawableFrame(
                AsTool.getContent(),
                tintColor
            )
        } else {
            getDrawable(
                AsTool.getContent(),
                R.drawable.toast_frame
            )
        }
        setBackground(toastLayout, drawableFrame)
        if (withIcon) {
            requireNotNull(icon) { "Avoid passing 'icon' as null if 'withIcon' is set to true" }
            setBackground(toastIcon, icon)
        } else {
            toastIcon.visibility = View.GONE
        }
        toastTextView.setTextColor(textColor)
        toastTextView.text = message
        toastTextView.typeface = Typeface.create(TOAST_TYPEFACE, Typeface.NORMAL)
        currentToast?.view = toastLayout
        if (gravity != 0) {
            currentToast?.setGravity(gravity, xOffset, yOffset)
        }
        currentToast?.duration = duration
        return currentToast
    }

    private fun tint9PatchDrawableFrame(context: Context?, @ColorInt tintColor: Int): Drawable? {
        if (context == null) {
            return null
        }
        val toastDrawable = getDrawable(
            context,
            R.drawable.toast_frame
        ) as NinePatchDrawable?
        toastDrawable?.colorFilter = PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)
        return toastDrawable
    }

    private fun getDrawable(context: Context?, @DrawableRes id: Int): Drawable? {
        if (context == null) {
            return null
        }
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            context.getDrawable(id)
        } else {
            context.resources.getDrawable(id)
        }
    }

    private fun setBackground(view: View, drawable: Drawable?) {
        view.background = drawable
    }
}